class_name RTSSelectionNode extends Node2D

#region 信号
## 选择单位的信号
signal units_selected(selected_units: Array[Node])
#endregion 信号

#region 枚举

#endregion 枚举

#region 导出属性
#region 选择框属性设置
@export_group("选择框属性设置")
## 选择框的边框宽度
@export_range(0.0, 10.0, 1.0) var selection_box_border_width: float = 3.0
## 选择框的边框颜色
@export_color_no_alpha var selection_box_border_color: Color = Color.BLUE
## 选择框边框颜色的Alpha分量。在 0 到 1 的范围内。0 表示该颜色完全透明。1 表示该颜色完全不透明。
@export_range(0.0, 1.0, 0.1) var selection_box_border_color_alpha: float = 0.5
## 是否用填充色填充选择框。如果选择框的宽度或者高度小于边框宽度的两倍，不会绘制填充色。
@export var selection_box_filled: bool = true
## 选择框的填充色
@export_color_no_alpha var selection_box_fill_color: Color = Color.SKY_BLUE
## 选择框填充色的Alpha分量。在 0 到 1 的范围内。0 表示该颜色完全透明。1 表示该颜色完全不透明。
@export_range(0.0, 1.0, 0.1) var selection_box_fill_color_alpha: float = 0.5
#endregion 选择框属性设置

#region 单位分组名称设置
@export_group("单位分组名称设置")
## 己方单位的分组名称
@export var own_units_group_names: Array[String] = [ "own_unit" ]
## 己方建筑的分组名称[br]
## (注意：建筑属于特殊类型的单位，只有点击才能选中建筑)
@export var own_buildings_group_names: Array[String] = [ "own_building" ]
## 盟友单位的分组名称
@export var allied_units_group_names: Array[String] = [ "allied_unit" ]
## 盟友建筑的分组名称
@export var allied_buildings_group_names: Array[String] = [ "allied_building" ]
## 敌方单位的分组名称
@export var enemy_units_group_names: Array[String] = [ "enemy_unit" ]
## 敌方建筑的分组名称
@export var enemy_buildings_group_names: Array[String] = [ "enemy_building" ]
#endregion 单位分组名称设置

#region 选择设置
@export_group("选择设置")
## 最大选择数量，0表示无限制
@export_range(0, 99999, 1) var max_selection_count: int = 0
#endregion 选择设置
#endregion 导出属性

# 选择框的起点
var _selection_start_point: Vector2 = Vector2.ZERO
# 双击
var _double_click: bool = false

# 处理输入
func _input(event: InputEvent) -> void:
	# 处理鼠标输入
	var input_event_mouse_button: InputEventMouseButton = event as InputEventMouseButton
	if input_event_mouse_button and input_event_mouse_button.button_index == MOUSE_BUTTON_LEFT:
		if input_event_mouse_button.pressed:
			_double_click = input_event_mouse_button.double_click
			if _selection_start_point == Vector2.ZERO:
				_selection_start_point = get_global_mouse_position()
		elif (_selection_start_point != Vector2.ZERO and not input_event_mouse_button.pressed):
			var mouse_position: Vector2 = get_global_mouse_position()
			var ctrl_pressed: bool = input_event_mouse_button.ctrl_pressed or input_event_mouse_button.meta_pressed
			var shift_pressed: bool = input_event_mouse_button.shift_pressed
			if _double_click:
				# 双击
				_handle_double_click(mouse_position, ctrl_pressed, shift_pressed)
			else:
				if mouse_position.is_equal_approx(_selection_start_point):
					# 单击
					_handle_click(mouse_position, ctrl_pressed, shift_pressed)
				else:
					# 框选
					_handle_range_select(mouse_position, ctrl_pressed, shift_pressed)
			_selection_start_point = Vector2.ZERO
	# 处理键盘输入
	var input_event_key: InputEventKey = event as InputEventKey
	if input_event_key and not input_event_key.pressed:
		var keycode: Key = input_event_key.keycode
		var ctrl_pressed: bool = input_event_key.ctrl_pressed or input_event_key.meta_pressed
		var shift_pressed: bool = input_event_key.shift_pressed
		_handle_key_press(keycode, ctrl_pressed, shift_pressed)
		
func _process(_delta: float) -> void:
	queue_redraw()
	
## 绘制
func _draw() -> void:
	_draw_selection_box()


## 绘制选择框
func _draw_selection_box() -> void:
	if _selection_start_point == Vector2.ZERO:
		return
	var mouse_position: Vector2 = get_global_mouse_position()
	#绘制边框
	var rect: Rect2 = Utility2D.get_rect_from_two_points(_selection_start_point, mouse_position)
	var border_color: Color = Color(selection_box_border_color, selection_box_border_color_alpha)
	draw_rect(rect, border_color, false, selection_box_border_width)
	#绘制填充色
	if (not selection_box_filled or rect.size.x <= selection_box_border_width * 2 or 
		rect.size.y <= selection_box_border_width * 2):
		return
	var fill_rect: Rect2 = rect.grow(-1.0 * selection_box_border_width)
	var fill_color: Color = Color(selection_box_fill_color, selection_box_fill_color_alpha)
	draw_rect(fill_rect, fill_color, true, -1.0, false)


## 选择单位，并发出信号
func _select_units() -> void:
	if units_selected.get_connections().is_empty():
		return
	var mouse_position: Vector2 = get_global_mouse_position()
	var rect: Rect2 = Utility2D.get_rect_from_two_points(_selection_start_point, mouse_position)
	
	var units_in_group: Array[Node] = get_tree().get_nodes_in_group("unit_group_name")
	var selected_units: Array[Node] = []
	if not units_in_group.is_empty():
		for unit: Node in units_in_group:
				selected_units.append(unit)
	units_selected.emit(selected_units)
		

# 选择单位事件处理
func _on_units_selected(selected_units: Array[Node]) -> void:
	if selected_units != null and not selected_units.is_empty():
		for selected_unit: Node in selected_units:
			var unit: Unit = selected_unit as Unit
			if is_instance_valid(unit):
				unit.selected = true


# 处理双击
func _handle_double_click(mouse_position: Vector2, ctrl_pressed: bool, shift_pressed: bool) -> void:
	print("double click", mouse_position, ctrl_pressed,shift_pressed)
	pass
	

# 处理单击
func _handle_click(mouse_position: Vector2, ctrl_pressed: bool, shift_pressed: bool) -> void:
	print("click", mouse_position, ctrl_pressed,shift_pressed)
	pass
	

# 处理框选
func _handle_range_select(mouse_position: Vector2, ctrl_pressed: bool, shift_pressed: bool) -> void:
	print("range select", mouse_position, ctrl_pressed,shift_pressed)
	pass
	

# 处理按键
func _handle_key_press(keycode: int, ctrl_pressed: bool, shift_pressed: bool) -> void:
	print("key press", keycode, ctrl_pressed,shift_pressed)
	pass


# 获取所有的单位、建筑分组名称数组
func _get_all_group_names() -> Array[String]:
	var names: Array[String] = []
	if own_units_group_names and not own_units_group_names.is_empty():
		names.append_array(own_units_group_names)
	if own_buildings_group_names and not own_buildings_group_names.is_empty():
		names.append_array(own_buildings_group_names)
	if allied_units_group_names and not allied_units_group_names.is_empty():
		names.append_array(allied_units_group_names)
	if allied_buildings_group_names and not allied_buildings_group_names.is_empty():
		names.append_array(allied_buildings_group_names)
	if enemy_units_group_names and not enemy_units_group_names.is_empty():
		names.append_array(enemy_units_group_names)
	if enemy_buildings_group_names and not enemy_buildings_group_names.is_empty():
		names.append_array(enemy_buildings_group_names)
	return names



	


# 获取特定位置第一个匹配的单位
func _get_first_unit_at_point(pos: Vector2) -> Node:
	var scene_tree: SceneTree = get_tree()
	var unit: Node
	unit = Utility2D.get_first_unit_in_groups_at_point(scene_tree, own_units_group_names, pos)
	if unit:
		return unit
	unit = Utility2D.get_first_unit_in_groups_at_point(scene_tree, own_buildings_group_names, pos)
	if unit:
		return unit
	unit = Utility2D.get_first_unit_in_groups_at_point(scene_tree, allied_units_group_names, pos)
	if unit:
		return unit
	unit = Utility2D.get_first_unit_in_groups_at_point(scene_tree, allied_buildings_group_names, pos)
	if unit:
		return unit
	unit = Utility2D.get_first_unit_in_groups_at_point(scene_tree, enemy_units_group_names, pos)
	if unit:
		return unit
	unit = Utility2D.get_first_unit_in_groups_at_point(scene_tree, enemy_buildings_group_names, pos)
	if unit:
		return unit
	return null


# 获取当前视口中相同的单位
func _get_same_units_in_viewport(groups: Array[String], unit: Node) -> Array[Node]:
	var scene_tree: SceneTree = get_tree()
	if not scene_tree:
		return []
	var canvas_item: CanvasItem = unit as CanvasItem
	if not canvas_item:
		return []
	var range: Rect2 = Utility2D.get_viewport_rect(canvas_item)
	var dict: Dictionary = Utility2D.get_units_in_groups_in_range(scene_tree, groups, range)
	var class_and_script_name: String = Utility2D.get_object_class_and_script_name(unit)
	var units: Dictionary = Utility2D.get_units_in_class(dict, class_and_script_name)
	if not units or units.is_empty():
		return []
	return units.values()


func _ready() -> void:
	pass
